import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { User } from '../user/entities/user.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { LoginDto } from './dto/LoginDto';
import { LocalStrategy } from "./local.strategy";
import { MenuService } from '../menu/menu.service';
@Injectable()
export class AuthService {
  constructor(
    private jwtService: JwtService,
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
    private LocalStrategy: LocalStrategy,
    private readonly menuService: MenuService
  ) { }

  // 生成token
  // Partial<User> 表示 User 实体中的属性为可选的
  // 这里不需要再传入密钥，因为在auth.module.ts中已经配置了，
  //并且设置成全局模块说明所有使用到jwt.service的地方都会自动使用这个密钥
  createToken(user: Partial<User>, expiresIn: string) {
    return this.jwtService.sign({ ...user }, { expiresIn });
  }


  // 登录
  async login(user: LoginDto) {
    // 校验用户名密码,成功返回用户信息
    const newUser = await this.LocalStrategy.validate(user.username, user.password)
    // console.log(newUser);

    // 短token
    const access_token = this.createToken({
      username: newUser.username,
      id: newUser.id
    }, "300s"
    );

    // 长token
    const refresh_token = this.createToken({
      username: newUser.username,
      id: newUser.id
    }, "7d"
    );

    return {
      userInfo: { ...newUser, password: undefined },
      access_token,
      refresh_token
    };
  }

  // 刷新token
  async refreshToken(token: string) {
    console.log(token);

    const isValid = this.jwtService.verify(token)
    if (!isValid) {
      throw new Error('token无效')
    } else {
      const access_token = this.createToken({
        username: isValid.username,
        id: isValid.id
      }, "300s");
      // 长token
      const refresh_token = this.createToken({
        username: isValid.username,
        id: isValid.id
      }, "7d");
      // console.log(isValid);
      return { access_token, refresh_token }
    }
  }

  // 登录之后调用此方法，查询用户所拥有的菜单
  async queryUserMenu(query) {
    const userId = query.userId
    const user = await this.userRepository.findOne({ where: { id: userId }, relations: ['roles', 'roles.menu'] })

    // 使用 Map 去重
    const uniqueMenusMap = new Map<string, any>();
    // console.log(user);
    user.roles.forEach(role => {
      role.menu.forEach(menu => {
        uniqueMenusMap.set(menu.id, menu);
      });
    });
    const roleMenu = Array.from(uniqueMenusMap.values())

    const allParentMenu = await Promise.all(roleMenu.map(async (menu) => {
      return await this.menuService.findAllParentMenu(menu)
    }))

    // console.log(allParentMenu);

    const allParentMenuMap = new Map()

    allParentMenu.forEach(menu => {
      menu.forEach(menuItem => {
        allParentMenuMap.set(menuItem.id, menuItem)
      })
    })

    const allMenu = Array.from(allParentMenuMap.values())

    const builderMenuTree = (menuList, parentId = "0") => {
      const menuTree = []
      menuList.forEach(menu => {
        if (menu.parentId === parentId) {
          menuTree.push({
            ...menu,
            children: builderMenuTree(menuList, menu.id)
          })
        }
      })
      return menuTree
    }

    const menuTree = builderMenuTree(allMenu)
    // console.log(menuTree);
    // return {}
    return menuTree
  }

  async getUser(user) {
    return await this.userRepository.findOne({ where: { username: user.username } })
  }

}
